package Stana.hierarchicalClustering;

import java.util.ArrayList;
import java.util.List;


public class PriceQuantityCluster {
	private List<PriceQuantityItem> items;
	private double medianPrice;
	private double higherPrice = 0;
	private double lowerPrice = Double.MAX_VALUE;
	private double medianQuantity;
	private double higherQuantity = 0;
	private double lowerQuantity = Double.MAX_VALUE;
	private double priceSum = 0; // FOR MEAN
	private double quantitySum = 0; // FOR MEAN

	// Constructor of empty cluster with a specified median (for K-means)
	public PriceQuantityCluster(double medianPrice, double medianQuantity) {
		this.items = new ArrayList<PriceQuantityItem>();
		this.medianPrice = medianPrice;
		this.medianQuantity = medianQuantity;
		
	}

	public PriceQuantityCluster(List<PriceQuantityItem> newItems) {
		this.items = new ArrayList<PriceQuantityItem>(newItems);
		calculateMedianPrice();
		calculateMedianQuantity();
	}

	public PriceQuantityCluster(List<PriceQuantityItem> newItems, List<PriceQuantityItem> newItems2) {
		this.items = new ArrayList<PriceQuantityItem>(newItems);
		items.addAll(newItems2);
		calculateMedianPrice();
		calculateMedianQuantity();
	}

	public PriceQuantityCluster(PriceQuantityItem item) {
		this.items = new ArrayList<PriceQuantityItem>();
		this.items.add(item);
		// calculate median
		this.medianPrice = item.getPrice();
		this.medianQuantity = item.getQuantity();
	}

	// To perform merges
	public void addItemsFromCluster(PriceQuantityCluster cluster2) {
		for (PriceQuantityItem item : cluster2.getItems()) {
			getItems().add(item);
			priceSum += item.getPrice();
			quantitySum += item.getQuantity();
		}
	}

	public void addItem(PriceQuantityItem item) {
		getItems().add(item);
		priceSum += item.getPrice();
		quantitySum += item.getQuantity();
	}

	public void addItems(List<PriceQuantityItem> newItems) {
		for (PriceQuantityItem item : newItems) {
			this.getItems().add(item);
			priceSum += item.getPrice();
			quantitySum += item.getQuantity();
		}
	}

	public List<PriceQuantityItem> getItems() {
		return items;
	}

	public int size() {
		return getItems().size();
	}

	public double getMedianPrice() {
		return medianPrice;
	}

	public double getMedianQuantity() {
		return medianQuantity;
	}	
	
	public String toString() {
		String retour = "";
		
		if (getItems().size() != 0) {
			retour = "(";
			for (PriceQuantityItem item : getItems()) {
				retour = retour + item.getProdName() + " " + 
							item.getQuantity() + "  " +  item.getPrice() +  " ";
			}
			retour = retour + ")      <" + medianQuantity + "," + medianPrice + ", min=" +
				getLowerQuantity() + ","+ getLowerPrice() + "," 
				+   " max=" + getHigherQuantity() + "," + getHigherPrice() + ">";
		}

		return retour;
	}

	private void calculateMedianQuantity() {
		if (getItems().isEmpty()) {
			return;
		}

		if (getItems().size() == 1) {
			medianQuantity = getItems().get(0).getPrice();
			return;
		}
		// VERSION USING THE AVERAGE
		medianQuantity = quantitySum / ((double) items.size());

	}
	
	
	private void calculateMedianPrice() {
		if (getItems().isEmpty()) {
			return;
		}

		if (getItems().size() == 1) {
			medianPrice = getItems().get(0).getPrice();
			return;
		}
		// VERSION USING THE AVERAGE
		medianPrice = priceSum / ((double) items.size());

	}

	public void recomputeClusterMedianPrice() {
		calculateMedianPrice();
	}
	public void recomputeClusterMedianQuantity() {
		calculateMedianQuantity();
	}

	
	public void computeHigherAndLowerPrice() {
		for (PriceQuantityItem item : getItems()) {
			if (item.getPrice() > higherPrice) {
				higherPrice = item.getPrice();
			}
			if (item.getPrice() < lowerPrice) {
				lowerPrice = item.getPrice();
			}
		}
	}

	public void computeHigherAndLowerQuantity() {
		for (PriceQuantityItem item : getItems()) {
			if (item.getQuantity() > higherQuantity) {
				higherQuantity = item.getQuantity();
			}
			if (item.getQuantity() < lowerQuantity) {
				lowerQuantity = item.getQuantity();
			}
		}
	}

	
	public boolean containsItem(PriceQuantityItem item2) {
		for (PriceQuantityItem item : getItems()) {
			if (item == item2) {
				return true;
			}
		}
		return false;
	}

	public double getHigherPrice() {
		return higherPrice;
	}

	public double getLowerPrice() {
		return lowerPrice;
	}
	public double getHigherQuantity() {
		return higherQuantity;
	}

	public double getLowerQuantity() {
		return lowerQuantity;
	}

}
